package com.moodincode.taskcenter.service.impl;

import com.moodincode.taskcenter.bean.JobProxy;
import com.moodincode.taskcenter.bean.TaskInfo;
import com.moodincode.taskcenter.service.IQuartzService;
import com.moodincode.taskcenter.service.IQuartzTaskService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * @author moodincode
 */
@Service
@Slf4j
public class QuartzServiceImpl implements IQuartzService {
    /**
     * spring quartz定时器工厂
     */
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private IQuartzTaskService quartzTaskService;

    /**
     * 获取所有任务
     * @return
     */
    @Override
    public List<TaskInfo> findAll() {
        return quartzTaskService.findAll();
    }

    /**
     * 获取任务
     * @param id
     * @return
     */
    @Override
    public TaskInfo getTaskById(String id){
        return quartzTaskService.getById(id);
    }
    /**
     * 暂停一个定时任务
     * @param id
     * @return
     */
    @Override
    public TaskInfo pauseTask(String id){
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
            scheduler.pauseTrigger(triggerKey);
            refreshTaskState(task, scheduler, triggerKey);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }

    /**
     * 创建任务
     * @param task
     * @return
     * @throws Exception
     */
    @Override
    public TaskInfo createTask(TaskInfo task) throws  Exception {
        Scheduler scheduler=schedulerFactoryBean.getScheduler();
        JobKey jobKey=new JobKey(task.getName(), task.getGroup());

        TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
        if(scheduler.checkExists(jobKey)||scheduler.checkExists(triggerKey)){
            throw new RuntimeException("已存在相同ID的任务");
        }
        Class<?> cls = Class.forName(task.getCls());
        Class <? extends Job> jobCls;
        //判断是否继承JOB
        boolean isUserDefine=false;
        if(cls.newInstance() instanceof Job){
            jobCls= (Class<? extends Job>) cls;
        }else{
            isUserDefine=true;
            jobCls= JobProxy.class;
        }
        JobDetail job = JobBuilder.newJob(jobCls)
                .withIdentity(jobKey)
                .build();
        if(isUserDefine){
            job.getJobDataMap().put(JobProxy.DATA_JOB_BEAN_CLASS_NAME,task.getCls());
            job.getJobDataMap().put(JobProxy.DATA_JOB_METHOD_NAME,task.getMethod());
        }


        //
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(triggerKey)
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule(task.getCron()))
                .build();

        // Tell quartz to schedule the job using our trigger
        scheduler.scheduleJob(job, trigger);
        //刷新任务状态
        refreshTaskState(task,scheduler,triggerKey);
        return task;


    }

    private void refreshTaskState(TaskInfo task, Scheduler scheduler, TriggerKey triggerKey) throws SchedulerException {
        Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
        if(state!=null){
            task.setState(state.ordinal());
            quartzTaskService.save(task);
        }
    }

    /**
     * 修改一个定时任务
     * @param id
     * @return
     */
    @Override
    public TaskInfo modifyTask(String id, String cron,String script){
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
            CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
            String oldCron= trigger.getCronExpression();
            if(!oldCron.equalsIgnoreCase(cron)){
                //删除任务
                removeTask(id);
                task.setCron(cron);
                task.setScript(script);
                //重新添加任务
                createTask(task);
            }else if(!ObjectUtils.nullSafeEquals(task.getScript(),script)){
                task.setScript(script);
                quartzTaskService.save(task);

            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }
    /**
     * 删除一个定时任务
     * @param id
     * @return
     */
    @Override
    public  TaskInfo removeTask(String id){
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            JobKey jobKey = new JobKey(task.getName(), task.getGroup());
            scheduler.deleteJob(jobKey);
            quartzTaskService.delete(id);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }
    /**
     * 重启一个定时任务
     * @param id
     * @return
     */
    @Override
    public  TaskInfo restartTask(String id){
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
            scheduler.resumeTrigger(triggerKey);
            //刷新任务状态
            refreshTaskState(task,scheduler,triggerKey);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }

    /**
     * 关闭一个定时任务
     * @param id
     * @return
     */
    @Override
    public  TaskInfo shutdownTask(String id){
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            TriggerKey triggerKey = new TriggerKey(task.getTrigger(), task.getGroup());
            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            JobKey jobKey = new JobKey(task.getName(), task.getGroup());
            scheduler.deleteJob(jobKey);
            task.setState(-1);
            quartzTaskService.save(task);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }

    @Override
    public TaskInfo triggerTask(String id) {
        TaskInfo task=getTaskById(id);
        try {
            Scheduler scheduler=schedulerFactoryBean.getScheduler();
            JobKey jobKey=new JobKey(task.getName(), task.getGroup());
            scheduler.triggerJob(jobKey);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        return task;
    }

    /**
     * 启动所有定时任务
     */
    @Override
    public void startAllTask() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.start();
            //重新检查任务状态
            refreshAllTaskState();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 关闭所有定时任务
     */
    @Override
    public void shutdownAllTask() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();

            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
            //重新检查任务状态
            refreshAllTaskState();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 重启所有定时任务
     */
    @Override
    public void resumeAllTask() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.resumeAll();
            //重新检查任务状态
            refreshAllTaskState();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 暂停所有定时任务
     */
    @Override
    public void pauseAllTask() {
        try {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            scheduler.pauseAll();
            //重新检查任务状态
            refreshAllTaskState();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 刷新任务状态
     */
    private void refreshAllTaskState() {
        List<TaskInfo> infoList = quartzTaskService.findAll();
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        infoList.stream().forEach(task->{
            try {
                Trigger.TriggerState state = scheduler.getTriggerState(new TriggerKey(task.getTrigger(), task.getGroup()));
                if(state!=null){
                    //判断和更新状态
                    if(state.ordinal()!=task.getState()){
                        task.setState(state.ordinal());
                        quartzTaskService.save(task);
                    }

                }
            } catch (SchedulerException ex) {
                log.error("刷新所有任务状态失败");
            }
        });
    }
}
